////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
//  File name:   MusicSystem.h
//  Version:     v1.00
//  Created:     26/7/2004 by Timur.
//  Compilers:   Visual Studio.NET 2003
//  Description: 
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#ifndef __MusicSystem_h__
#define __MusicSystem_h__
#pragma once

#include "../StdAfx.h"

#include <vector>
#include <IMusicSystem.h>
#include <ITimer.h>
#include <smartptr.h>
#include "Pattern/MusicPattern.h"
#include "../IPlatformSound.h" // tSoundHandle
#include "MusicCVars.h"

#ifndef __SPU__
#ifdef SOUNDSYSTEM_USE_FMODEX400
#include <FmodEx/inc/fmod.hpp>
#include <FmodEx/inc/fmod_event.hpp>
#endif
#endif

#if (defined(WIN32) || defined(WIN64)) && defined(INCLUDE_AUDIO_PRODUCTION_CODE)
  //#define MUSIC_FORCE_QUEUED_TRACKS  // This makes the PC behave the same way as consoles to keep parity.
#endif // (_WIN32 || _WIN64) && INCLUDE_AUDIO_PRODUCTION_CODE

#define FADE_STREAM_UNROLL 32

// Forward declarations
struct ISystem;
struct IAudioDevice;

// Info-Structure for automated fading
struct SMusicPatternPlayInfo
{
	SMusicPatternPlayInfo()
	{
		nLayer						=	MUSICLAYER_MAIN;
		pPatternInstance	=	NULL;
		eBlendType				=	EBlend_None;
		ePlayingType			=	EPlaying_Loop;
		pRefCount					=	NULL;
		fPhase						=	1.0;
		fFadeTime					=	0.0;	// use default fade time...
		nSamplesToWait    = 0;
		nStartFromPos			= 0;
		bRefCountAdjusted	=	false;
		bForceChange			= false;
		bFadeOutMainTracks = false;
		bForceTrack1			= false;
		bForceTrack2			= false;
	}
	~SMusicPatternPlayInfo()
	{
		pPatternInstance	=	NULL;
	}
	unsigned int				nLayer;
	TPatternInstancePtr pPatternInstance;
	EBlendingType				eBlendType;
	EPlayingType				ePlayingType;
	int const*					pRefCount;
	// internal
	float	fPhase;			// phase for fading (0-1)
	float	fFadeTime;	// time in seconds to fade
	int     nSamplesToWait;
	int			nStartFromPos;
	bool		bRefCountAdjusted;
	bool		bForceChange;
	// queued info
	bool		bFadeOutMainTracks;
	bool		bForceTrack1;
	bool		bForceTrack2;
};

// holds all required data from SMusicPatternPlayInfos for MixStreamsKernel
struct SMusicPatternPlayInfoHolder
{
	float					fFade;
	int						nSamplesToWait;	
	unsigned int	nSamples;
	unsigned int	pad16;			
} _ALIGN(16);

// Info structures for queued requests
enum EMusicSystemQueudRequestType 
{
	eMSQRT_None,
	eMSQRT_PlayPattern,
	eMSQRT_SetMood,
	eMSQRT_SetTheme,
	eMSQRT_EndTheme,
	eMSQRT_PlayStart,
	eMSQRT_PlayStinger
};

struct SMusicSystemQueuedRequest 
{
	SMusicSystemQueuedRequest()
		:	eMusicSystemQueudRequestType(eMSQRT_None),
			bStopPrevious(false),
			bPlaySynched(false),
			bPlayOnTop(false),
			bPlayFromStart(false),
			bForceChange(false),
			bKeepMood(false),
			nDelayInSec(0),
			eBlendingType(EBlend_None),
			eThemeFadeType(EThemeFade_StopAtOnce),
			nForceEndLimitInSec(0),
			bEndEverything(false){}

	EMusicSystemQueudRequestType eMusicSystemQueudRequestType;

	// Globals
	string					sName;

	// PlayPattern specifics
	bool						bStopPrevious;
	bool						bPlaySynched;
	bool            bPlayOnTop;

	// SetMood, SetTheme and EndTheme specifics
	bool						bPlayFromStart;
	bool						bForceChange;
	bool						bKeepMood;
	int							nDelayInSec;
	EThemeFadeType	eThemeFadeType;
	int							nForceEndLimitInSec;
	bool						bEndEverything;

	// PlayStart specifics
	EBlendingType	eBlendingType;
};

//////////////////////////////////////////////////////////////////////////
// A couple of typedefs for various stl-containers
//////////////////////////////////////////////////////////////////////////

typedef std::map<string,CMusicPattern*,stl::less_stricmp<string> >	TPatternMap;
typedef TPatternMap::iterator										TPatternMapIt;
typedef TPatternMap::const_iterator							TPatternMapItConst;

typedef std::vector<string>											TStringVec;
typedef TStringVec::iterator										TStringVecIt;
typedef TStringVec::const_iterator							TStringVecItConst;

typedef std::vector<SMusicPatternPlayInfo>			TPatternPlayInfoVec;
typedef TPatternPlayInfoVec::iterator						TPatternPlayInfoVecIt;
typedef TPatternPlayInfoVec::const_iterator			TPatternPlayInfoVecItConst;

typedef std::vector<SMusicSystemQueuedRequest>	TQueuedRequestsVec;
typedef TQueuedRequestsVec::iterator						TQueuedRequestsVecIt;
typedef TQueuedRequestsVec::const_iterator			TQueuedRequestsVecItConst;

//////////////////////////////////////////////////////////////////////////
// Structure to collect/handle mood-events
//////////////////////////////////////////////////////////////////////////

struct SMoodEventInfo
{
	bool operator<(const SMoodEventInfo &b) const
	{
		if (stricmp(sMood.c_str(), b.sMood.c_str()) < 0)
			return true;
		return false;
	}
	string	sMood;	// name of mood
	float		fTime;	// time of consecutive event-occurance
};

typedef std::set<SMoodEventInfo>	TMoodEventSet;
typedef TMoodEventSet::iterator		TMoodEventSetIt;

//////////////////////////////////////////////////////////////////////////
// The MusicSystem itself
//////////////////////////////////////////////////////////////////////////

class CMusicSystem : public IMusicSystem, public CMusicCVars, public ISystemEventListener
{
protected:
	
	// notification sink
	IMusicSystemSink *m_pSink;

	// sound-playback params
	float m_fMasterVolume;
	int		m_nSampleRate;
	float m_fLatency;
	
	// bytes/sample in output stream
	int m_nBytesPerSample;
	
	// temporary mix-buffer
	void *m_pPatternMixBuffer;	// m_CSMusic_MixBuffers
	void *m_pMixBuffer;					// m_CSMusic_MixBuffers

	//corresponding count to m_MixStreamsPlayInfos
	unsigned int m_MixStreamsPlayInfosCnt; // m_CSMusic_MixBuffers

	enum {EMixStreamsPlayInfoSize = 16};
	//temp array of mix stream Playinfo inputs for MixStreamsKernel to mix all at once
	SMusicPatternPlayInfoHolder m_MixStreamsPlayInfos[EMixStreamsPlayInfoSize] _ALIGN(128);		

	// fmod stream data
	tAssetHandle	m_pStream;				// m_CSMusic_FMOD_specific
	IAudioDevice	*m_pAudioDevice;	// m_CSMusic_FMOD_specific
	void					*m_pChannel;			// m_CSMusic_FMOD_specific

#ifdef SOUNDSYSTEM_USE_FMODEX400
	FMOD_RESULT m_ExResult;
#endif

	// states
	bool m_bDataLoaded;
	bool m_bPause;
	bool m_bPlaying;
	bool m_bBridging;							// bridging in progress
	bool m_bCurrPatternIsBridge;
	bool m_bForcePatternChange;		// change pattern asap (next fadepoint), do not play to the end (last fadepoint)
	bool m_bNeedUpdate;						// Try to update again if we failed to get the Lock during the last frame

	// status
	SMusicSystemStatus m_Status;
	
	// all patterns
	TPatternMap m_mapPatterns; // m_CSMusic_Data_mapPatterns
	
	// current main patterns
	
	TPatternInstancePtr m_pTrack1;	// m_CSMusic_Tracks
	int m_Track1Type;								// m_CSMusic_Tracks
	
	TPatternInstancePtr m_pTrack2;	// m_CSMusic_Tracks
	int m_Track2Type;								// m_CSMusic_Tracks

	TPatternInstancePtr m_pNextTrack;	// m_CSMusic_Tracks
	int m_NextTrackType;							// m_CSMusic_Tracks

	TPatternInstancesVec m_PatternInstances; // m_CSMusic_PatternInstances
	TPatternInstancesVec m_PatternInstancesToBeRemoved; // m_CSMusic_PatternInstancesToBeRemoved;
	TPatternInstancesVec m_PatternInstancesRemovedFromStreamingThread; // m_CSMusic_PatternInstancesRemovedFromStreamingThread;

	int m_nLayeredRhythmicPatterns; // m_CSMusic_PatternInstances
	int m_nLayeredIncidentalPatterns; // m_CSMusic_PatternInstances

	// array of currently playing patterns
	TPatternPlayInfoVec m_vecPlayingPatterns; // m_CSMusic_vecPlayingPatterns
	
	// array of currently queued patterns
	TPatternPlayInfoVec m_vecQueuedPatterns; // CS to use is pending

	// array of patterns to play once level starts after serializing
	TPatternPlayInfoVec m_vecQueuedLoadPatterns;

	// all themes (moods inside)
	TThemeMap m_mapThemes; // m_CSMusic_Data_ThemesAndMoods
	
	// current theme/mood
	SMusicTheme *m_pCurrTheme; // m_CSMusic_Data_ThemesAndMoodsPointers;
	// in case a theme change occurred, NextTheme is the new theme... NULL otherwise
	SMusicTheme *m_pNextTheme; // m_CSMusic_Data_ThemesAndMoodsPointers;
	SMusicMood	*m_pCurrMood;  // m_CSMusic_Data_ThemesAndMoodsPointers;
	SMusicMood	*m_pNextMood;  // m_CSMusic_Data_ThemesAndMoodsPointers;

	// Timer
	CTimeValue m_MoodTime;
	CTimeValue m_ThemeTime;
	CTimeValue m_ThemeSetTime;
	int				 m_nDelayThemeInSec;

	CTimeValue m_tLastUpdate;
	
	// mood event arrays
	TMoodEventSet m_setMoodEvents;			// active mood events
	TMoodEventSet m_setFrameMoodEvents;	// mood events arrived last frame
	
	// default mood
	//SMusicMood *m_pDefaultMood;
	float		m_fDefaultMoodTime;					// current time 'till default-mood-timeout
	string	m_sDefaultMood;							// override of theme-specific default-mood (set by SetDefaultMood); set to "" to use theme-specific
	
	// fading
	float m_fCurrCrossfadeTime;
	
	// logging
	TStringVec	m_vecLog;
	bool				m_bEnableEventProcessing;
	int					m_musicEnable;
	uint32			m_UpdateTicks;					//ticks of last update

	bool m_bWaitForQueuedPatterns;
	bool m_bForceQueuedRequests;

	SMusicSystemInfo m_oMusicSystemInfo;

private:

	TQueuedRequestsVec        m_aoQueuedRequests;
	static TMoodsHierarchyVec m_aoMoodsHierarchy;

	typedef std::vector<IMusicSystemEventListener*>	MusicSystemEventListeners;
	MusicSystemEventListeners m_apEventListeners;

	typedef std::vector<EMusicSystemCallbackEvent> MusicSystemEventQueue;
	MusicSystemEventQueue m_aeQueuedMusicSystemEvents;

	XmlNodeRef m_oMusicStateNode; // This is needed for when the caller doesn't provide a TSerialize object for serialization.

#ifdef INCLUDE_AUDIO_PRODUCTION_CODE
	struct SDrawInfoInternal
	{
		SDrawInfoInternal()
		: nNumThemes(0),
		  nNumMoods(0),
			nNumPatterns(0),
			nNumPatternInstances(0),
			nNumPatternInstancesRemovedFromStreamingThread(0)
		{}

		~SDrawInfoInternal()
		{
			stl::free_container(aoPlayingPatternInfos);
			stl::free_container(aoQueuedPatterns);
			stl::free_container(aoQueuedLoadPatterns);
			stl::free_container(aoPatternInstances);
			stl::free_container(aoPatternInstancesToBeRemoved);
			stl::free_container(aoPatternInstancesRemovedFromStreamingThread);
			stl::free_container(sTheme);
			stl::free_container(sMood);
			stl::free_container(sTrack1Name);
			stl::free_container(sTrack2Name);
			stl::free_container(sNextTrackName);
		}

		size_t              nNumThemes;
		size_t              nNumMoods;
		size_t              nNumPatterns;
		size_t              nNumPatternInstances;
		size_t              nNumPatternInstancesRemovedFromStreamingThread;
		CryFixedStringT<64> sTheme;
		CryFixedStringT<64> sMood;
		CryFixedStringT<64> sTrack1Name;
		CryFixedStringT<64> sTrack2Name;
		CryFixedStringT<64> sNextTrackName;

		struct SPatternInfoInternal
		{
			SPatternInfoInternal()
				: fVolume(0.0f),
				  fCurrentVolume(0.0f),
				  fProgress(0.0f),
					fNextFade(0.0f),
					nNumReferences(0),
					nNumInstances(0),
					nBufferFillPercentage(0)
			{
				memset(fColor, 0, sizeof(fColor));
			}

			~SPatternInfoInternal()
			{
				stl::free_container(sLayer);
				stl::free_container(sPatternName);
				stl::free_container(sPatternFileName);
			}

			float                fColor[4];
			CryFixedStringT<16>  sLayer;
			CryFixedStringT<64>  sPatternName;
			CryFixedStringT<128> sPatternFileName;
			float                fVolume;
			float                fCurrentVolume;
			float                fProgress;
			float                fNextFade;
			int                  nNumReferences;
			int                  nNumInstances;
			int unsigned         nBufferFillPercentage;
		};

		std::vector<SPatternInfoInternal> aoPlayingPatternInfos;
		std::vector<SPatternInfoInternal> aoQueuedPatterns;
		std::vector<SPatternInfoInternal> aoQueuedLoadPatterns;
		std::vector<SPatternInfoInternal> aoPatternInstances;
		std::vector<SPatternInfoInternal> aoPatternInstancesToBeRemoved;
		std::vector<SPatternInfoInternal> aoPatternInstancesRemovedFromStreamingThread;
	};

	typedef std::vector<SDrawInfoInternal::SPatternInfoInternal> TPatternInfoInternalVec;
	SDrawInfoInternal m_oDrawInfoInternal;
#endif // INCLUDE_AUDIO_PRODUCTION_CODE

protected:

	virtual ~CMusicSystem();

	bool StartPlaying();
	bool StopPlaying();
	void Silence();
	void FadeOutAllSecondaryLayers(float const fFadeTime);

	//Pattern
	bool										FlushPatterns();
	bool const							PushPatternToMixList(SMusicPatternPlayInfo &PlayInfo);
	bool										UpdateCurrentPatternSet(SMusicMood *pMood, int nSamples, bool bAllowChange);
	bool										ChoosePatternSet(SMusicMood *pMood, const bool bUseSameIndex=false);
	CMusicPattern*					AddPattern(const char *pszName, const char *pszFilename);
	CMusicPatternInstance*	GetPatternInstance(const char *pszPattern);
	CMusicPatternInstance*	ChooseBridge(SMusicTheme *pCurrTheme, SMusicTheme *pNewTheme);
	CMusicPatternInstance*	ChoosePattern(SMusicMood *pMood, const int nLayer);

	// Mood
	void				EnterDefaultMood();
	bool				SetMood(SMusicMood *pNewMood, const bool bPlayFromStart=true, const bool bForceChange=true);
	SMusicMood* GetMood(SMusicTheme *pTheme, const char *pszMood) const;
	SMusicMood* GetDefaultMood(SMusicTheme *pTheme) const;

	// Theme
	bool SetTheme(SMusicTheme *pNewTheme, bool bForceChange);
	
	// Stream
	void MixStreams(void *const __restrict pBuffer, int nLength);
	bool FadeStreamIn(SMusicPatternPlayInfo& PlayInfo, int16* pBuffer, size_t const nSamples) const;
	bool FadeStreamOut(SMusicPatternPlayInfo& PlayInfo, int16* pBuffer, size_t const nSamples) const;

	// Callbacks
	void StreamingCallback(tAssetHandle pStream, void* pBuffer, int nLength);

#if (defined SOUNDSYSTEM_USE_FMODEX400)
	//#pragma message (">>> Music-callback declaration:")
	friend FMOD_RESULT F_CALLBACK _StreamingCallback(FMOD_SOUND *sound, void *data, unsigned int datalen);
#endif

	// ISystemEventListener
	virtual void OnSystemEvent( ESystemEvent event,UINT_PTR wparam,UINT_PTR lparam );
	// ~ISystemEventListener

public:

	CMusicSystem();
	
	// System
	bool              Init();
	void              Shutdown();
	void							Release();
	void							ReleaseData();
	void							Unload();
	IMusicSystemSink* SetSink(IMusicSystemSink *pSink);
	bool							SetData( struct SMusicInfo::Data *pMusicData );
	void							Update();

	// Information
	int									GetBytesPerSample() { return m_nBytesPerSample; }
	SMusicSystemStatus* GetStatus();		// retrieve status of music-system... dont keep returning pointer !
	void								ClearStatus();	// removes current temp data
	virtual bool				IsPlaying() const { return m_bPlaying; }
	virtual bool				IsPatternFading() const; // returns true if there is a pattern in the queue that is currently fading (meaning it's not EBlend_None)

	//! compute memory-consumption
	void								GetMemoryUsage(class ICrySizer* pSizer) const;
	virtual bool				IsNullImplementation() const { return false; }
	
	// Playback
	void Pause(bool bPause);
	ILINE bool IsPaused() const { return m_bPause; }
	void EnableEventProcessing(bool bEnable) { m_bEnableEventProcessing = bEnable; }

	// Theme
	VIRTUAL bool	SetTheme(const char *pszTheme, bool bForceChange=true, bool bKeepMood=true, int nDelayInSec=-1, char const* const sStartMood = NULL);
	virtual bool	EndTheme(EThemeFadeType ThemeFade=EThemeFade_FadeOut, int nForceEndLimitInSec=10, bool bEndEverything=false);
	const char*		GetTheme() const { if (m_pCurrTheme) return m_pCurrTheme->sName.c_str(); return ""; }
	IStringItVec* GetThemes() const;
	virtual CTimeValue GetThemeTime() const { return gEnv->pTimer->GetFrameStartTime() - m_ThemeTime; }

	// Mood
	bool					SetMood(const char *pszMood, const bool bPlayFromStart=true, const bool bForceChange=false);
	bool					SetDefaultMood(const char *pszMood);
	const char*		GetMood() const { if (m_pCurrMood) return m_pCurrMood->sName.c_str(); return ""; }	
	IStringItVec* GetMoods(const char *pszTheme) const;
	bool					AddMusicMoodEvent(const char *pszMood, float fTimeout);
	virtual CTimeValue GetMoodTime() const { return gEnv->pTimer->GetFrameStartTime() - m_MoodTime; };
	VIRTUAL TMoodsHierarchyVec const& GetMusicMoodHierarchy() const { return m_aoMoodsHierarchy; }

	// Patterns
	VIRTUAL IStringItVec* const GetPatterns() const;

	//////////////////////////////////////////////////////////////////////////
	//! Load music data from XML.
	//! @param bAddAdata if true data from XML will be added to currently loaded music data.
	bool LoadFromXML( const char *sFilename, bool bAddData, bool bReplaceData);
	bool LoadFromXMLNode( const XmlNodeRef root, bool bAddData, bool bReplaceData);

	//////////////////////////////////////////////////////////////////////////
	// Editing support.
	//////////////////////////////////////////////////////////////////////////
	virtual void UpdatePattern( SMusicInfo::Pattern *pPattern );
	virtual void RenamePattern( const char *sOldName,const char *sNewName );
	virtual void PlayPattern(char const* const sPattern, bool const bStopPrevious, bool const bPlaySynched, bool const bPlayOnTop);
	VIRTUAL bool StopPattern(char const* const sPatternNameToStop);
	virtual void DeletePattern( const char *sPattern );
	VIRTUAL char const* const GetPatternNameTrack1() const;

	virtual void PlayStinger();

#ifdef INCLUDE_AUDIO_PRODUCTION_CODE
	// Production only stuff
	VIRTUAL void DrawInformation(IRenderer* const pRenderer, float xpos, float ypos);
	void LogMsg( const int nVerbosity, const char *pszFormat, ... ) PRINTF_PARAMS(3, 4);
#else
	void LogMsg( const int nVerbosity, const char *pszFormat, ... ){} PRINTF_PARAMS(3, 4);
#endif // INCLUDE_AUDIO_PRODUCTION_CODE

	// For serialization where the called passed its own TSerialize object for serialization.
	VIRTUAL void Serialize(TSerialize ser);

	// For serialization where the called doesn't provide a TSerialize object for serialization.
	VIRTUAL void Serialize(bool const bSave);

	virtual float GetUpdateMilliseconds();
	void MixStreamsKernel(void *const __restrict pBuffer, int nSamplesToCopy, unsigned int mixStreamsPlayInfosCnt, void *m_pPatternMixBuffer);

	// Register and remove a listener
	VIRTUAL void AddEventListener(IMusicSystemEventListener* const pListener);
	VIRTUAL void RemoveEventListener(IMusicSystemEventListener* const pListener);

private:
	//////////////////////////////////////////////////////////////////////////
	// Loading.
	//////////////////////////////////////////////////////////////////////////
	void LoadPatternFromXML(	XmlNodeRef node,	SPatternDef *pPattern );
	void LoadMoodFromXML(			XmlNodeRef &node,	SMusicMood *pMood );
	void LoadThemeFromXML(		XmlNodeRef &node,	SMusicTheme *pTheme );
	void UpdatePatternDef( SPatternDef *pPattern );

	SMusicPatternPlayInfo* GetAnotherPlayingPatternInstance(CMusicPattern* pPattern, CMusicPatternInstance* thisPatternInstance);
	SMusicPatternPlayInfo* GetPlayingPatternInfo( const int nLayer, const EBlendingType BlendType );
	SMusicPatternPlayInfo* GetPlayingPatternInfo(TPatternInstancePtr pPattern, TPatternPlayInfoVec** pPatternVec);
	bool IsPatternPlaying( const TPatternInstancePtr pPattern );
	bool AllPatternsAreReady() const;

	bool PlayStart(EBlendingType eBlendType);

	//helper routine for MixStreams
	void MixStreamsStreamEnds(SMusicPatternPlayInfo & PlayInfo);
	//need all args to bypass cache entirely on spu
	
	void PushBackPlayInfo(const SMusicPatternPlayInfo & PlayInfo, int nSamples)
	{
		assert(m_MixStreamsPlayInfosCnt < EMixStreamsPlayInfoSize);
		if (m_MixStreamsPlayInfosCnt < EMixStreamsPlayInfoSize)
		{
			SMusicPatternPlayInfoHolder &curPlayInfo = m_MixStreamsPlayInfos[m_MixStreamsPlayInfosCnt++];
			curPlayInfo.nSamples				= nSamples;
			curPlayInfo.nSamplesToWait	= PlayInfo.nSamplesToWait;
			curPlayInfo.fFade						= 1.0f;
			if (PlayInfo.pPatternInstance && PlayInfo.pPatternInstance->GetPattern())
				curPlayInfo.fFade = PlayInfo.pPatternInstance->GetPattern()->GetLayeringVolume();
			else
			{
				assert(0);
			}
		}
	}
	void CreatePlayInfoFromPattern(TPatternInstancePtr pPattern, SMusicPatternPlayInfo& PlayInfo);

	void	FadeOutMainTracks(bool const bForceChange);
	void	ReleaseXMLNode(XmlNodeRef& rXMLNode);
	void  QueueEvent(EMusicSystemCallbackEvent const eEvent);
	void  SendEventsToListeners();
	void  SetTrack1(CMusicPatternInstance* const pNewTrack1, int const nLayerType);
	void  SetTrack2(CMusicPatternInstance* const pNewTrack2, int const nLayerType);
	void  SetNextTrack(CMusicPatternInstance* const pNewNextTrack, int const nLayerType);
	void  ForceFinishLoadingPattern(CMusicPatternInstance const* const pPatternToFinish) const;
	void  ForceFinishAllPatterns();

#ifdef INCLUDE_AUDIO_PRODUCTION_CODE
	void DrawInformationPlayInfoVec(IRenderer* pRenderer, float& xpos, float& ypos, TPatternInfoInternalVec const& raoPatternInfos);
	void DrawInformationPatternInstancesVec(IRenderer* pRenderer, float& xpos, float& ypos, TPatternInfoInternalVec const& raoPatternInfos);
	void FlushLog();
	void UpdateDrawInfoInternal();
	void FillPatternPlayInfo(TPatternPlayInfoVec const& rPatternPlayInfos, TPatternInfoInternalVec& rPatternInfosInternal);
	void FillPatternInstanceInfo(TPatternInstancesVec const& rPatternInstancesInfos, TPatternInfoInternalVec& rPatternInfosInternal);
#else
	void FlushLog() {}
#endif // INCLUDE_AUDIO_PRODUCTION_CODE
};

//////////////////////////////////////////////////////////////////////////
// String-vector-class to iterate data from other DLLs
//////////////////////////////////////////////////////////////////////////

class CStringItVec : public IStringItVec, public CPoolAllocSystem
{
public:
	CStringItVec(TStringVec &Vec)
	{
		m_nRefCount=0;
		m_Vec=Vec;
		MoveFirstImpl();
	};

	VIRTUAL bool IsEnd() { return (m_itVec==m_Vec.end()); };
	VIRTUAL const char* Next() { return IsEnd() ? "" : (*m_itVec++).c_str(); };
	VIRTUAL void MoveFirst() { MoveFirstImpl(); };
	VIRTUAL void AddRef() { m_nRefCount++; }
	VIRTUAL void Release() { --m_nRefCount; if (m_nRefCount<=0) { delete this; } };
	void MoveFirstImpl() { m_itVec = m_Vec.begin(); };

protected:
	int m_nRefCount;
	TStringVec m_Vec;
	TStringVecIt m_itVec;
};

#endif // __MusicSystem_h__
